
package com.studiofortress.sf.audio;

import com.studiofortress.sf.util.Repeater;
import java.io.IOException;
import java.io.InputStream;

/**
 * Repeatedly reads in the bytes from the given input stream into the audio
 * buffer provided by this class.
 *
 * @author Joseph Lenton - JosephLenton@StudioFortress.com
 */
class AudioLoader extends Repeater
{
    private static final int DEFAULT_AUDIO_BUFFER_SIZE = 2048;
    
    private final InputStream input;
    private final byte[] readBuffer;
    private final AudioBuffer audioBuffer;

    public AudioLoader(InputStream input, AudioBuffer audioBuffer)
    {
        this( input, audioBuffer, DEFAULT_AUDIO_BUFFER_SIZE );
    }

    /**
     * @param input The stream reading the audio from, cannot be null.
     * @param audioBuffer The AudioBuffer to write the input too, cannot be null.
     * @param readBufferSize The ideal size of each number of bytes to read from the InputStream, must be greater then 0.
     */
    public AudioLoader(InputStream input, AudioBuffer audioBuffer, int readBufferSize)
    {
        if (input == null) {
            throw new IllegalArgumentException("The given input cannot be null.");
        } else if (audioBuffer == null) {
            throw new IllegalArgumentException("The given audioBuffer cannot be null.");
        } else if (readBufferSize <= 0) {
            throw new IllegalArgumentException("The readBufferSize must be greater then 0, was given: " + readBufferSize);
        }

        this.input = input;
        this.readBuffer = new byte[ readBufferSize ];
        this.audioBuffer = audioBuffer;
    }

    /**
     * Continually reads data in from the InputStream and into the AudioBuffer.
     */
    @Override
    public void repeat()
    {
        try {
            final int read = input.read( readBuffer );
            
            if (read > 0) {
                audioBuffer.addBuffer( readBuffer, read );
            } else if (read < 0) {
                input.close();
                audioBuffer.finish();
                stopRepeating();
            }
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
}
